import React, { useEffect, useRef, useState } from 'react';
import { message, Tooltip, Popconfirm, Spin } from 'antd';
import { debounce } from 'lodash';
import cn from 'classnames';
import { CSSTransition, SwitchTransition } from 'react-transition-group';
import events from '@/utils/eventBus';
import WEBSOCKET_TYPES from '@/pages/Recruitment/Interview/utils/WEBSOCKET_TYPES';
import EVENTBUS_TYPES from '@/pages/Recruitment/Interview/utils/EVENTBUS_TYPES';
import WARNING_TYPES from '@/pages/Recruitment/Interview/utils/WARNING_TYPES';
import { formatTime, isHttps } from '@/pages/Recruitment/Interview/utils/utils';
import useNetWorkState from '@/pages/Recruitment/Interview/hooks/useNetWorkState';
import styles from './style.less';
import RECAnimation from '../RECAnimation';

const debounceOpt = {
    leading: true,
    trailing: false
};

// 获取主录音头像
const getHostHead = (hostUserCode, interviewersArr) => {
    for (let index = 0; index < interviewersArr.length; index += 1) {
        const item = interviewersArr[index];
        if (item.employeeCode === hostUserCode) return item.employeeAvatar;
    }
    return '';
};
// 获取名字
const getName = (userCode, interviewersArr) => {
    for (let index = 0; index < interviewersArr.length; index += 1) {
        const item = interviewersArr[index];
        if (item.employeeCode === userCode) return item.employeeName;
    }
    return '';
};

const RECController = ({
    recData,
    onBeforeStart,
    getRecInfo,
    userCode,
    recHOSTuserCode,
    remoteRECState,
    remoteRECStateRef,
    recorderState,
    interviewersArr,
    fightForHost,
    isDragging,
    duration = '00:00:00',
    realTimeRECRef,
    remoteRECDuration,
    warningType
}) => {
    const [unStartList, setUnStartList] = useState([]); // 未开始面试的面试官列表
    const blockRef = useRef(false); // 启动录音、继续录音，防抖用变量
    const onlineStateRef = useNetWorkState(); // 浏览器在线状态
    const [recControllerLoading, setRecControllerLoading] = useState(false); // 录音控制器所需的loading
    const proxyblockRefSetting = state => {
        blockRef.current = state;
        setRecControllerLoading(state);
    };

    /**
     * 检查浏览器在线状态
     * @returns 在线 true，离线 false
     */
    const checkOnlineState = () => {
        if (!onlineStateRef.current) {
            message.error('网络异常，请等待网络恢复后再次尝试。');
            return false;
        }
        return true;
    };

    /**
     * 发送录音开始信息到非录音者
     */
    const handleMsg = () => {
        events.emit(WEBSOCKET_TYPES.SHOW_MESSAGE, {
            msgType: 'success',
            userCode,
            msg: `${getName(userCode, interviewersArr)}已开启录音`
        });
    };

    const isFirstRef = useRef(true); // 区分是否为首次开启录音
    const hasInitRef = useRef(false); // 检查是否已 init,用于主录音 -》 旁听 =》再次抢夺主录音
    /**
     * 移除主录音相关监听
     */
    const removeListener = () => {
        events.removeListener(EVENTBUS_TYPES.HOST_FIGHT_RESULT);
    };
    /**
     * 继续录音
     */
    const handleRECResume = async sendMsg => {
        if (!checkOnlineState()) {
            return;
        }
        if (blockRef.current) {
            console.log('防抖！');
            return;
        }
        proxyblockRefSetting(true);
        const res = await getRecInfo();
        const duration1 = res.recordTimeInfo ? JSON.parse(res.recordTimeInfo)?.endTime : 0;
        console.log('handleRECResume,', duration1);
        removeListener();
        events.addListener(EVENTBUS_TYPES.HOST_FIGHT_RESULT, result => {
            removeListener();
            proxyblockRefSetting(false);
            if (result) {
                // 结果成功获取主录音，则执行这个
                message.success('已开启录音');
                console.log('handleRECResume----');
                realTimeRECRef.current.resumeRec(duration1);
                if (sendMsg) handleMsg();
            }
        });
        fightForHost(); // 启动主录音争夺
    };

    // 主录音权限获取成功后的操作,启动录音
    const afterGetHOST = () => {
        if (isFirstRef.current) {
            message.success('已开启录音，同时也可针对面试问题进行录音标记');
            isFirstRef.current = false;
        } else {
            console.log('afterGetHOST---');
            message.success('已开启录音');
        }
        realTimeRECRef.current.startRecAndUpload();
    };

    // 组件卸载时删除主录音相关事件的监听
    useEffect(() => {
        events.addListener(EVENTBUS_TYPES.SET_BLOCK, proxyblockRefSetting);
        return () => {
            removeListener();
            events.removeListener(EVENTBUS_TYPES.SET_BLOCK, proxyblockRefSetting);
        };
    }, []);

    const start = async sendMsg => {
        if (!checkOnlineState()) {
            return;
        }
        proxyblockRefSetting(true);
        const res = await getRecInfo();
        const duration1 = res.recordTimeInfo ? JSON.parse(res.recordTimeInfo)?.endTime : 0;
        realTimeRECRef.current.initRecInstance(res.recordContinueKey, duration1).then(
            () => {
                console.log('录音初始化成功');
                events.emit(EVENTBUS_TYPES.SET_WARNING, WARNING_TYPES.NONE);
                hasInitRef.current = true;
                // 这里需要检查主录音是否已经被他人夺走。夺走就不继续往下走了。 本处函数可能会异步执行，因为用户可能很长时间后才会去点击允许录音的弹窗。
                if (remoteRECStateRef.current === 1) {
                    proxyblockRefSetting(false);
                    return;
                }
                // 注册监听主录音获取成功的事件
                removeListener();
                events.addListener(EVENTBUS_TYPES.HOST_FIGHT_RESULT, result => {
                    proxyblockRefSetting(false);
                    removeListener();
                    if (result) {
                        // 结果成功获取主录音，则执行这个
                        afterGetHOST();
                        if (sendMsg) {
                            // 夺取主录音权限的情况下，发送msg到其它端
                            handleMsg();
                            // 夺取主录音权限的情况下，收起面试官列表
                            events.emit(EVENTBUS_TYPES.SET_EXTEND, false);
                        }
                    }
                });
                fightForHost(); // 启动主录音争夺
            },
            () => {
                // 判断录音启动成功 or 失败，失败后要弹出提示， 用eventBus传递出去。
                console.log('录音启动失败');
                proxyblockRefSetting(false);
                if (remoteRECStateRef.current === 1) {
                    return; // 如果主录音已经被抢走，就不出现警告了。
                }
                // 加入http、https连接判断，如果是http连接，则出现message
                if (isHttps(window.location.href)) {
                    events.emit(EVENTBUS_TYPES.SET_WARNING, WARNING_TYPES.ERROR);
                } else {
                    message.error('请使用https打开本网页,以支持录音!');
                }
            }
        );
    };
    /**
     * 启动录音
     * sendMsg 是否发送弹窗消息到其他端
     */
    const handleRECStart = (sendMsg = false) => {
        if (!checkOnlineState()) {
            return;
        }
        if (blockRef.current) {
            console.log('防抖！');
            return;
        }
        if (!recHOSTuserCode) {
            // 主录音未启动过的情况下，显示弹窗
            onBeforeStart().then(unStartList1 => {
                if (unStartList1.length) {
                    // 未进入的面试官，显示在弹窗中
                    setUnStartList(unStartList1);
                    document.querySelector('#popConfirmAnchor').click();
                } else {
                    start(sendMsg);
                }
            });
        } else if (!hasInitRef.current) {
            // 主录音启动过，但本人未获取过主录音权限的情况
            start(sendMsg);
        } else {
            proxyblockRefSetting(false);
            handleRECResume();
        }
    };

    /**
     * 停止录音
     */
    const handleRECStop = debounce(
        () => {
            if (!checkOnlineState()) {
                return;
            }
            realTimeRECRef.current.stopRec();
        },
        2000,
        debounceOpt
    );

    /**
     * 暂停录音
     */
    const handleRECPause = debounce(
        () => {
            realTimeRECRef.current.pauseRec();
            message.warning('已暂停录音');
        },
        2000,
        debounceOpt
    );
    // 掉线后回显的时间
    const [fakeDuration, setFakeDuration] = useState('00:00:00');
    useEffect(() => {
        if (recData.recordTimeInfo) {
            setFakeDuration(formatTime(JSON.parse(recData.recordTimeInfo).endTime));
        }
    }, [recData]);

    /**
     * 渲染停止按钮
     */
    const renderStopIcon = () => (
        <Tooltip placement="top" title="完成录音">
            <Popconfirm
                title={
                    <div>
                        <div>确定要停止录制?</div>
                        <div className={styles.recordHint}>录音一旦停止不可再次开启</div>
                    </div>
                }
                onConfirm={handleRECStop}
                okText="确定"
                getPopupContainer={() => document.querySelector('#popConfirmAnchor1')}
                autoAdjustOverflow
            >
                <div className={styles.controlIconWrapper}>
                    <i className={cn('iconfont iconstop_record_Icon', styles.scaleIconFont, styles.stopIcon)} />
                </div>
            </Popconfirm>
        </Tooltip>
    );

    /**
     * 获取拖拽时样式
     */
    const getDraggingStyle = () => {
        if (isDragging && !WARNING_TYPES.RED_LIST.includes(warningType)) {
            return styles.isDragging;
        }
        return '';
    };

    /**
     * 本人是主录音 or 主录音尚未设置 or 主录音异常掉线后，刷新页面重新进入
     *
     * 最后一种情况：
     * (userCode === recHOSTuserCode && recorderState === -1)
     * 主录音异常掉线后，重新开启页面,此时显示本特殊页面，
     * 提供继续录音（实际点下去就是非主录音的--开启录音）
     * 停止录音（仅设置状态）
     * 时间显示--直接从 recData --- recordTimeInfo --- endTime 获取
     */
    const renderAsHost = () => (
        <div className={cn(styles.RECController, getDraggingStyle())}>
            <Popconfirm
                title={
                    <div>
                        <div style={{ maxWidth: '192px' }}>{unStartList.join('、')}还未开始面试，是否开始录音?</div>
                    </div>
                }
                onConfirm={() => {
                    start(true);
                }}
                okText="确定"
                getPopupContainer={() => document.querySelector('#popConfirmAnchor1')}
                autoAdjustOverflow
            >
                <div id="popConfirmAnchor" className={styles.popConfirmAnchor}></div>
            </Popconfirm>
            {recorderState === 2 || (userCode === recHOSTuserCode && recorderState === -1) ? ( // 波纹扩散动画。录音已暂停，或主录音刷新页面
                <>
                    <div className={styles.expandAnimation1}></div>
                    <div className={cn(styles.expandAnimation1, styles.addDelay)}></div>
                </>
            ) : null}
            {recorderState !== -1 || (userCode === recHOSTuserCode && recorderState === -1) ? ( // 录音启动后 ，或主录音刷新页面
                <div className={styles.controllers}>
                    <div className={styles.placeHolder}>
                        {/* 录制中显示 */}
                        <CSSTransition
                            in={recorderState === 1}
                            timeout={150}
                            classNames={{
                                enter: styles.RECControllBtnEnter,
                                enterActive: styles.RECControllBtnEnterActive,
                                enterDone: styles.RECControllBtnEnterDone,
                                exit: styles.RECControllBtnExit,
                                exitActive: styles.RECControllBtnExitActive
                            }}
                            unmountOnExit
                        >
                            <Tooltip placement="top" title="暂停">
                                <div
                                    className={cn(styles.controlIconWrapper, styles.addCircle)}
                                    onClick={handleRECPause}
                                >
                                    <i className={cn('iconfont iconPause_F', styles.scaleIconFont, styles.pauseIcon)} />
                                </div>
                            </Tooltip>
                        </CSSTransition>
                        {/* 暂停录制显示，需要动画 */}
                        <CSSTransition
                            in={recorderState === 2}
                            timeout={150}
                            classNames={{
                                enter: styles.RECControllBtnEnter,
                                enterActive: styles.RECControllBtnEnterActive,
                                enterDone: styles.RECControllBtnEnterDone,
                                exit: styles.RECControllBtnExit,
                                exitActive: styles.RECControllBtnExitActive
                            }}
                            unmountOnExit
                        >
                            <Tooltip placement="top" title="继续录音">
                                <div
                                    className={cn(styles.controlIconWrapper, styles.addCircle)}
                                    onClick={() => {
                                        handleRECResume(true);
                                    }}
                                >
                                    <i
                                        className={cn('iconfont iconpause', styles.pauseIcon)}
                                        style={{ fontSize: '16px' }}
                                    />
                                </div>
                            </Tooltip>
                        </CSSTransition>
                        {/* 暂停录制显示，需要动画 */}
                        <CSSTransition
                            in={userCode === recHOSTuserCode && recorderState === -1}
                            timeout={150}
                            classNames={{
                                enter: styles.RECControllBtnEnter,
                                enterActive: styles.RECControllBtnEnterActive,
                                enterDone: styles.RECControllBtnEnterDone,
                                exit: styles.RECControllBtnExit,
                                exitActive: styles.RECControllBtnExitActive
                            }}
                            unmountOnExit
                        >
                            <Tooltip placement="top" title="继续录音">
                                <div
                                    className={cn(styles.controlIconWrapper, styles.addCircle)}
                                    onClick={() => {
                                        handleRECStart(true);
                                    }}
                                >
                                    <i
                                        className={cn('iconfont iconplayMark', styles.scaleIconFont, styles.pauseIcon)}
                                        style={{ fontSize: '16px' }}
                                    />
                                </div>
                            </Tooltip>
                        </CSSTransition>
                    </div>
                    {/* 停止录音按钮 */}
                    {renderStopIcon()}
                    <div className={styles.smallCol}></div>
                    <div className={styles.timeText}>
                        {userCode === recHOSTuserCode && recorderState === -1 ? fakeDuration : duration}
                    </div>
                </div>
            ) : null}
            {/* 录音启动前 */}
            <CSSTransition
                in={!(recorderState !== -1 || (userCode === recHOSTuserCode && recorderState === -1))}
                timeout={150}
                classNames={{
                    exit: styles.startWrapperExit,
                    exitActive: styles.startWrapperExitActive
                }}
                unmountOnExit
            >
                <div className={styles.flexWrapper}>
                    <CSSTransition
                        in={!(recorderState !== -1 || (userCode === recHOSTuserCode && recorderState === -1))}
                        timeout={150}
                        classNames={{
                            exit: styles.startBtnExit,
                            exitActive: styles.startBtnExitActive
                        }}
                        unmountOnExit
                    >
                        <div
                            className={cn(
                                styles.micIconWrapper,
                                warningType === WARNING_TYPES.ERROR ? styles.notAllowRECBG : ''
                            )}
                            onClick={() => {
                                handleRECStart(true);
                            }}
                        >
                            <i
                                className={cn(
                                    'iconfont iconrecordIcon',
                                    styles.whiteMic,
                                    warningType === WARNING_TYPES.ERROR ? styles.notAllowRECicon : ''
                                )}
                            />
                        </div>
                    </CSSTransition>
                    <CSSTransition
                        in={!(recorderState !== -1 || (userCode === recHOSTuserCode && recorderState === -1))}
                        timeout={150}
                        classNames={{
                            exit: styles.startTextExit,
                            exitActive: styles.startTextExitActive
                        }}
                        unmountOnExit
                    >
                        <span
                            className={cn(
                                styles.beforeStartText,
                                warningType === WARNING_TYPES.ERROR ? styles.notAllowRECfont : ''
                            )}
                            onClick={() => {
                                handleRECStart(true);
                            }}
                        >
                            开启录音
                        </span>
                    </CSSTransition>
                </div>
            </CSSTransition>
        </div>
    );

    // 本人不是主录音
    const renderAsClient = () => (
        <div className={cn(styles.RECController, getDraggingStyle())}>
            {remoteRECState !== 0 ? ( // 录音启动后
                <>
                    <CSSTransition
                        in={remoteRECState === 1 && recorderState !== 1} // 录制中显示
                        timeout={300}
                        classNames={{
                            enter: styles.audienceStartEnter,
                            enterActive: styles.audienceStartEnterActive,
                            enterDone: styles.audienceStartEnterDone,
                            exit: styles.audienceStartExit,
                            exitActive: styles.audienceStartExitActive,
                            exitDone: styles.audienceStartExitDone
                        }}
                        unmountOnExit
                    >
                        <div className={styles.controllers}>
                            <Tooltip placement="top" title={`${getName(recHOSTuserCode, interviewersArr)}正在录音`}>
                                <div className={styles.hostHeadWrapper}>
                                    <img
                                        className={styles.hostHead}
                                        src={getHostHead(recHOSTuserCode, interviewersArr)}
                                        alt=""
                                    />
                                    <div className={styles.headCover}>
                                        {warningType !== WARNING_TYPES.WARNING ? (
                                            <RECAnimation />
                                        ) : (
                                            <i
                                                className={cn(
                                                    styles.scaleIcon,
                                                    styles.redIcon,
                                                    'icon iconfont icona-Sounderror'
                                                )}
                                            ></i>
                                        )}
                                    </div>
                                </div>
                            </Tooltip>
                            <div className={styles.smallCol}></div>
                            <div className={styles.timeTextLight}>{formatTime(remoteRECDuration)}</div>
                        </div>
                    </CSSTransition>
                    <CSSTransition
                        in={remoteRECState === 2} // 暂停录制显示
                        timeout={300}
                        classNames={{
                            enter: styles.audienceStartEnter,
                            enterActive: styles.audienceStartEnterActive,
                            enterDone: styles.audienceStartEnterDone,
                            exit: styles.audienceStartExit,
                            exitActive: styles.audienceStartExitActive,
                            exitDone: styles.audienceStartExitDone
                        }}
                        unmountOnExit
                    >
                        <div className={styles.controllers}>
                            <div
                                className={styles.micIconWrapper}
                                onClick={() => {
                                    handleRECStart(true);
                                }}
                            >
                                <i className={cn('iconfont iconrecordIcon', styles.whiteMic)} />
                            </div>
                            <span
                                className={styles.beforeStartText}
                                onClick={() => {
                                    handleRECStart(true);
                                }}
                            >
                                开启录音
                            </span>
                        </div>
                    </CSSTransition>
                </>
            ) : // 录音启动前 + 本人非主录音 ,无需显示。因为实际上没有这个状态，录音启动前，是没有主录音的，因此也没有非主录音这种状态
            null}
        </div>
    );

    return (
        <Spin wrapperClassName={styles.RECController} spinning={recControllerLoading} delay={0}>
            <SwitchTransition>
                <CSSTransition
                    key={userCode === recHOSTuserCode || recHOSTuserCode === ''}
                    addEndListener={(node, done) => node.addEventListener('transitionend', done, false)}
                    classNames={{
                        enter: styles.wrapperStartEnter,
                        enterActive: styles.wrapperStartEnterActive,
                        enterDone: styles.wrapperStartEnterDone,
                        exit: styles.wrapperStartExit,
                        exitActive: styles.wrapperStartExitActive,
                        exitDone: styles.wrapperStartExitDone
                    }}
                    unmountOnExit
                >
                    {userCode === recHOSTuserCode || recHOSTuserCode === '' ? renderAsHost() : renderAsClient()}
                </CSSTransition>
            </SwitchTransition>
        </Spin>
    );
};

export default RECController;
